from numpy import *
import matplotlib.pyplot as plt

def lDataSet():
    dataMat = [];labelMat = []
    url = r'C:\Users\bgape\Desktop\computerS\machinelearninginaction\Ch05\testSet.txt'
    fr = open(url)
    for line in fr.readlines():
        lineArr = line.strip().split()
        dataMat.append([1,float(lineArr[0]),float(lineArr[1])])
        labelMat.append(float(lineArr[2]))
    return dataMat,labelMat

def dotplot():
    dataMat, labelMat = lDataSet()
    x1 = [];y1 = []
    x2 = [];y2 = []
    for i in range(len(labelMat)):
        if labelMat[i] == 0:
            x1.append(dataMat[i][1])
            y1.append(dataMat[i][2])
        else:
            x2.append(dataMat[i][1])
            y2.append(dataMat[i][2])
    plt.scatter(x1,y1,5)
    plt.scatter(x2,y2,5)
    plt.legend(['class0','class1'],loc=2)
    plt.show()

def sigmoid(inx):
    return 1/(1+exp(-inx))

def gradAscent(dataMatIn,classLabels,maxCycle):
    dataMatrix = mat(dataMatIn)
    labelsMat = mat(classLabels).transpose()
    n = shape(dataMatrix)[1]
    alpha = 0.001
    sample = zeros((maxCycle,n))
    weights = ones((n,1))
    for k in range(maxCycle):
        h = sigmoid(dataMatrix*weights)
        error = labelsMat-h
        weights = weights+alpha*dataMatrix.transpose()*error
        sample[k,:] = array(weights).T[0]
    return array(weights).T[0],sample.T

def stocGradAscent(dataArr,labelMat):
    dataArr = array(dataArr)
    m,n = shape(dataArr)
    alpha = 0.01
    weights = ones(n)
    for i in range(m):
        h = sigmoid(sum(dataArr[i]*weights))
        error = labelMat[i]-h
        weights = weights+alpha*error*dataArr[i]
    return weights

def stocGradAscent1(dataArr,labelMat,maxCycle=150):
    dataArr = array(dataArr)
    m,n = shape(dataArr)
    weights = ones(n)
    sample = zeros((maxCycle,n))
    for i in range(maxCycle):
        dataIndex = [i for i in range(m)]
        for j in range(m):
            alpha = 4/(1+i+j)+0.01
            #randIndex = int(random.uniform(0,len(dataIndex)))
            #del(dataIndex[randIndex])
            randIndex = int(random.uniform(0,m-j))
            #(0,len(dataIndex))产生一个服从均匀分布的随机数
            h = sigmoid(sum(dataArr[randIndex]*weights))
            error = labelMat[randIndex]-h
            weights = weights+alpha*error*dataArr[randIndex]
        sample[i,:] = weights
    return weights,sample.T

def plotBestFit(weights):
    dataMat, labelMat = lDataSet()
    x1 = [];y1 = []
    x2 = [];y2 = []
    for i in range(len(labelMat)):
        if labelMat[i] == 0:
            x1.append(dataMat[i][1])
            y1.append(dataMat[i][2])
        else:
            x2.append(dataMat[i][1])
            y2.append(dataMat[i][2])
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(x1,y1,s=10,c='r',marker='s')
    ax.scatter(x2,y2,s=10,c='g')
    ax.legend(['class0','class1'],loc=2)
    x = arange(-3,3,0.1)
    y = (-weights[0]-weights[1]*x)/weights[2]
    ax.plot(x,y)
    plt.xlabel('X1');plt.ylabel('X2');
    plt.show()

def plotBestFit(weights,maxCycle=0,fun=gradAscent,part=1):
    dataMat, labelMat = lDataSet()
    fig = plt.figure()
    ax = fig.add_subplot(111)
    if part==1:
        x1 = [];y1 = []
        x2 = [];y2 = []
        for i in range(len(labelMat)):
            if labelMat[i] == 0:
                x1.append(dataMat[i][1])
                y1.append(dataMat[i][2])
            else:
                x2.append(dataMat[i][1])
                y2.append(dataMat[i][2])
        ax.scatter(x1,y1,s=10,c='r',marker='s')
        ax.scatter(x2,y2,s=10,c='g')
        ax.legend(['class0','class1'],loc=2)
        x = arange(-3,3,0.1)
        y = (-weights[0]-weights[1]*x)/weights[2]
        ax.plot(x,y)
        plt.xlabel('X1');plt.ylabel('X2');
    else:
        y = fun(dataArr,labelMat,maxCycle)[1]
        x = array(range(maxCycle))
        ax.plot(x,y[0,:],color='r')
        ax.plot(x,y[1,:],color='g')
        ax.plot(x,y[2,:],color='b')
    plt.show()


dataArr,labelMat = lDataSet()
dataArr = array(dataArr)
w = stocGradAscent1(dataArr,labelMat)[0]
plotBestFit(w,150,stocGradAscent1,2)